﻿Imports Microsoft.VisualBasic

Namespace MyApp
    Namespace Network

        Public Class Facebook
            Private db As mDB = mDB.GetDB

            Public Property oauth2 As WebApi.Oauth.Oauth2

            Public Function RedirectAuth() As String

                Return oauth2.GetDialog("https://www.facebook.com/dialog/oauth", "manage_pages publish_stream")

            End Function
            'Public Function RedirectConfirmingIdentity() As String

            '    Return oauth2.GetConfirmingIdentity("https://graph.facebook.com/oauth/access_token")

            '    'Redirigo l'utente a twitter che ha capito chi sono e verifica se l'utente è loggato e se sì controlla che abbia l'autorizzazione con la mia applicazione
            '    'Return SF("https://www.facebook.com/dialog/oauth?client_id={0}&redirect_uri={1}", oauth2.client_id, HttpUtility.UrlEncode(oauth2.redirect_uri))

            'End Function


            Public Sub AddLogin(code As String, access_token As String)
                Dim db = mDB.GetDB
                Dim CurrUser = MyApp.GetUser(False)

                'L'utente riconosciuto da Twitter ci ha autorizzato, chiedo quindi a Twitter i dati dell'utente
                oauth2.access_token = access_token
                oauth2.code = code

                If access_token = "" Then
                    oauth2.ConfirmingIdentity("https://graph.facebook.com/oauth/access_token", "GET", "QUERY_STRING")
                End If

                Dim tc = New WebApi.Facebook.FacebookClient(oauth2)

                Dim tu = tc.GetCurrUser
                Dim PageIds = tu.accounts.data.Select(Function(o) o.id).ToList
                Dim Pages = tc.GetPagesLookup(String.Join(",", PageIds))

                For Each DataAcc In tu.accounts.data

                    '--------------------------------------------
                    ' creo account

                    Dim acc = Me.UpdateAccountPage(Pages(DataAcc.id))

                    '--------------------------------------------
                    ' creo user_account

                    Dim UserAcc = CurrUser.Tab_User_Account.BY.User_Account.Account_Id(acc.Id).Limit(1).ToObj

                    If UserAcc Is Nothing Then
                        UserAcc = New mDB.User_Account
                        db.TAB.User_Account.InsertOnSubmit(UserAcc)
                    End If

                    UserAcc.Account_Id = acc.Id
                    UserAcc.User_Id = CurrUser.Id
                    'UserAcc.Network_Id = AccType.FACEBOOK_PAGE
                    'UserAcc.Oauth_Consumer_Key = oauth2.client_id
                    'UserAcc.Oauth_Consumer_Secret = oauth2.client_secret
                    'UserAcc.Oauth_Token = DataAcc.access_token

                    db.SubmitChanges()

                Next

            End Sub


            Public Sub DownloadAccountPosts(Acc As mDB.Account)

                Const NumPostFindEnd = 100
                Const NumPostToDownload = 500
                'creo il client con i dati dell'account collegato
                Dim tc = New WebApi.Facebook.FacebookClient(Me.oauth2)

                Dim EndDownload = False
                Dim ContinuePrevDownload = False
                Dim Since = ""
                Dim Until = ""

                Dim IsUserAccount = Acc.Tab_User_Account.ToList.Count > 0

                Dim PostCount = 0

                Dim Codes = Acc.Account_Add_Info.Post_Last_Code.ToString.Split(",")

                If Codes.Length > 1 Then
                    ContinuePrevDownload = True
                    Since = Codes(0)
                    Until = Codes(1)
                Else
                    Since = Acc.GetLastPostDateUniversalTimeStamp ' Me.GetLastMessCod(Acc)
                End If

                MyApp.WriteProcLog(SF("(tab)(tab)FACEBOOK begin update post: {0} ({1})", Acc.Fullname, Acc.Username), Task.TaskType.UPDATE_ACCOUNTS)

                EndDownload = False
                Do Until EndDownload

                    Dim tweets As WebApi.Facebook.Results(Of WebApi.Facebook.Post)

                    Try

                        tweets = tc.GetPageFeed(Acc.Account_Code, Since, Until)

                    Catch ex As WebApi.Net.ExceptionAPIResponse

                        ' MyApp.WriteProcLog(SF("(tab)(tab)(tab)ExceptionRequest message: {0}, {1}", tc.LastError.Code, tc.LastError.Message), AutoProcType.UPDATE_ACCOUNTS)
                        Exit Do

                    End Try

                    MyApp.WriteProcLog(SF("(tab)(tab)(tab)post: {0}, {1}", tweets.data.Count, Acc.Username), Task.TaskType.UPDATE_ACCOUNTS)

                    PostCount += tweets.data.Count
                    For Each t In tweets.data
                        Me.UpdateAccountPost(Acc, t, IsUserAccount)
                    Next

                    If tweets.data.Count > 0 Then
                        Until = Utils.Conv.ToTimeStamp(tweets.data.Last.created_time.ToUniversalTime) ' tweets.Last.id_str
                    End If

                    Acc.Account_Add_Info.Post_Last_Code = SF("{0},{1}", Since, Until)
                    db.SubmitChanges()

                    If tweets.data.Count <= NumPostFindEnd Or PostCount > NumPostToDownload Then
                        EndDownload = True
                    End If

                    If EndDownload And ContinuePrevDownload Then
                        ContinuePrevDownload = False
                        EndDownload = False
                        Since = Acc.GetLastPostDateUniversalTimeStamp ' Me.GetLastMessCod(Acc)
                        Until = ""
                        PostCount = 0
                    End If

                Loop

                If EndDownload Then
                    Acc.Account_Add_Info.Post_Update = Now
                    Acc.Account_Add_Info.Post_Last_Code = ""
                    db.SubmitChanges()
                End If

                MyApp.WriteProcLog(SF("(tab)(tab)end update post: {0} ({1})", Acc.Fullname, Acc.Username), Task.TaskType.UPDATE_ACCOUNTS)

            End Sub

            Public Function UpdateAccountPost(Acc As mDB.Account, t As WebApi.Facebook.Post, SaveEntities As Boolean) As mDB._Account_Post

                'aggiorna messaggio
                Dim Post = Acc._Tab_Account_Post.BY._Account_Post._Post_Code(t.id).ToObj

                If Post Is Nothing Then
                    Post = New mDB._Account_Post
                    db.InsertOnSubmit(Acc.ArchivePost.Table_Name, Post)
                End If

                Post.Post_Code = t.id
                Post.Post_Text = MyApp.ToUTF8DB(t.message) 'Encoding.Default.GetString(Encoding.Convert(Encoding.UTF8, Encoding.Default, Encoding.UTF8.GetBytes(t.text)))
                Post.Pubb_Date = t.created_time
                Post.Account_Id = Acc.Id

                db.SubmitChanges()

                '-------------------------------------------------------
                ' messaggi
                ' IMPORTANTE se un post è una risposta ad un altro messaggio mette il post anche tra i messaggi
                If SaveEntities Then
                    If t.from.id <> Acc.Account_Code Or t.comments IsNot Nothing Then
                        Me.UpdateMessagePost(Acc, t)
                    End If
                End If

                Return Post

            End Function


#Region "ACCOUNT"

            Public Function DownloadAccounts(ids As List(Of String)) As List(Of mDB.Account)
                Dim tc = New WebApi.Facebook.FacebookClient(Me.oauth2)
                Dim NumUserPerRequest = 50
                Dim Accounts As New List(Of mDB.Account)


                Dim page = Int((ids.Count - 1) / NumUserPerRequest) + 1

                For ct = 1 To page

                    Dim Numids = NumUserPerRequest
                    If ct = page Then
                        Numids = ids.Count - ((page - 1) * NumUserPerRequest)
                    End If

                    Dim IdsCurrent = ids.GetRange((ct - 1) * NumUserPerRequest, Numids)
                    Dim IdsLookup = String.Join(",", IdsCurrent)

                    Dim tusers = tc.GetUsersLookup(IdsLookup)

                    MyApp.WriteProcLog(SF("(tab)(tab)update number user: {0}", Numids), Task.TaskType.UPDATE_ACCOUNTS)

                    For Each tu In tusers

                        Dim Acc = Me.UpdateAccount(tu.Value)
                        Accounts.Add(Acc)

                    Next

                    If tusers.Count = 0 And IdsCurrent.Count > 0 Then
                        MyApp.WriteProcLog(SF("(tab)(tab)account non exits: {0}", IdsLookup), Task.TaskType.UPDATE_ACCOUNTS)
                        Dim accids = db.TAB.Account.Where("account_code", "IN", IdsCurrent).ToList(Of Integer)("id")
                        If accids.Count > 0 Then
                            db.TAB.Account_Update.Where("account_id", "IN", accids).Update.UpdateValue("profile_update", Now.AddMonths(1)).ExecuteCommand()
                        End If

                    End If

                Next

                Return Accounts

            End Function

            Public Function DownloadAccountsPage(ids As List(Of String)) As List(Of mDB.Account)
                Dim tc = New WebApi.Facebook.FacebookClient(Me.oauth2)
                Dim NumUserPerRequest = 50
                Dim Accounts As New List(Of mDB.Account)


                Dim page = Int((ids.Count - 1) / NumUserPerRequest) + 1

                For ct = 1 To page

                    Dim Numids = NumUserPerRequest
                    If ct = page Then
                        Numids = ids.Count - ((page - 1) * NumUserPerRequest)
                    End If

                    'Dim tusers As List(Of WebApi.Twitter.User)
                    Dim IdsLookup = String.Join(",", ids.GetRange((ct - 1) * NumUserPerRequest, Numids))

                    Try

                        Dim tusers = tc.GetPagesLookup(IdsLookup)

                        MyApp.WriteProcLog(SF("(tab)(tab)update number user: {0}", Numids), Task.TaskType.UPDATE_ACCOUNTS)

                        For Each tu In tusers

                            MyApp.WriteProcLog(SF("(tab)(tab)(tab)user: {0} - {1} - {2}", tu.Value.id, tu.Value.username, tu.Key), Task.TaskType.UPDATE_ACCOUNTS)

                            If tu.Key <> "error" Then
                                Dim Acc = Me.UpdateAccountPage(tu.Value)
                                Accounts.Add(Acc)

                            End If

                        Next

                    Catch ex As WebApi.Net.ExceptionAPIAccount

                    End Try

                    'MyApp.WriteProcLog(SF("(tab)(tab) {0} - {1} - {2}", tusers.Values.Count, IdsLookup, tc.LastRes), AutoProcType.UPDATE_ACCOUNTS)



                Next

                Return Accounts

            End Function
            Public Function UpdateAccountPage(tu As WebApi.Facebook.Page) As mDB.Account

                '--------------------------------------------
                ' creo account
                Dim Acc = mDB.Account.GetForUpdate(tu.id, AccType.FACEBOOK_PAGE)
                'Dim Acc = db.TAB.Account.BY.Account.Account_Code(tu.id).ToObj

                'If Acc Is Nothing Then
                '    Acc = (New mDB.Account).SetDefault
                '    Acc.Network_Id = NetworkType.FACEBOOK_PAGE
                '    Acc.Account_Code = tu.id

                '    Acc.InsertOnSubmit(db)
                'End If

                Acc.Fullname = tu.name
                Acc.Username = tu.username
                Acc.Avatar = tu.picture.Data.url
                If tu.location IsNot Nothing Then
                    Acc.Location = tu.location.name
                End If
                Acc.Description = tu.about
                Acc.Url = tu.link

                Acc.Account_Add_Info.Profile_Update = Now
                Acc.Account_Add_Info.Follower_Count = tu.likes

                db.SubmitChanges()

                Return Acc

            End Function

            Public Function UpdateAccount(tu As WebApi.Facebook.User) As mDB.Account

                '--------------------------------------------
                ' creo account
                Dim Acc = mDB.Account.GetForUpdate(tu.id, AccType.FACEBOOK_USER)
                'Dim Acc = db.TAB.Account.BY.Account.Account_Code(tu.id).ToObj

                'If Acc Is Nothing Then
                '    Acc = (New mDB.Account).SetDefault
                '    Acc.Network_Id = NetworkType.FACEBOOK
                '    Acc.Account_Code = tu.id

                '    Acc.InsertOnSubmit(db)
                'End If

                Acc.Fullname = tu.name
                Acc.Username = tu.username
                Acc.Description = tu.bio

                If tu.picture IsNot Nothing Then
                    Acc.Avatar = tu.picture.data.url
                End If

                If tu.location IsNot Nothing Then
                    Acc.Location = tu.location.name
                End If

                Acc.Url = tu.link

                Acc.Account_Add_Info.Profile_Update = Now
                If tu.gender IsNot Nothing Then
                    If tu.gender.ToLower = "female" Then
                        Acc.Account_Add_Info.Gender_Type_Id = mDB.Gender_Name.Type.FEMALE
                    End If
                    If tu.gender.ToLower = "male" Then
                        Acc.Account_Add_Info.Gender_Type_Id = mDB.Gender_Name.Type.MALE
                    End If

                End If

                db.SubmitChanges()

                Return Acc

            End Function

#End Region

#Region "MESSAGE"



            Public Function UpdateMessagePost(Acc As mDB.Account, t As WebApi.Facebook.Post) As mDB.Message_Post

                'aggiorna messaggio
                Dim Mess = db.TAB.Message_Post.BY.Message_Post.Post_Code(t.id).ToObj

                If Mess Is Nothing Then
                    Mess = New mDB.Message_Post

                    '-------------------------------------------------------------
                    'crea l'account e il link come follewers
                    Dim AccCode = t.from.id '  t.user.id_str
                    If AccCode <> "" Then

                        Dim MessAcc = Acc.AddAccountLink(mDB._Account_Link.Type.FOLLOWER, AccCode, IIf(t.from.category = "", AccType.FACEBOOK_USER, AccType.FACEBOOK_PAGE))
                        Mess.Account_Id = MessAcc.Account_Link_Id

                    Else

                        Mess.Account_Id = 0

                    End If

                    db.InsertOnSubmit(Mess)

                End If

                Mess.Post_Code = t.id
                If Mess.Account_Id <> Acc.Id Then
                    Mess.To_Account_Id = Acc.Id
                Else
                    Mess.To_Account_Id = 0
                End If

                Mess.Post_Text = MyApp.ToUTF8DB(t.message) & " (" & MyApp.ToUTF8DB(t.story) & ")" & " [" & t.type.ToUpper & "]" ' Encoding.Default.GetString(Encoding.Convert(Encoding.UTF8, Encoding.Default, Encoding.UTF8.GetBytes(t.text)))
                Mess.Pubb_Date = t.created_time
                Mess.Hash_Id = Mess.Post_Text.GetHashCode

                db.SubmitChanges()

                'commenti
                If t.comments IsNot Nothing Then

                    Dim add As Boolean = False

                    For Each comm In t.comments.data
                        Dim m = Me.UpdateCommentPost(Acc, Mess, comm)
                        If m IsNot Nothing Then
                            add = True
                        End If
                    Next

                    If Not add Then
                        db.DeleteOnSubmit(Mess)
                        db.SubmitChanges()

                    End If

                End If


                Return Mess

            End Function

            Public Function UpdateCommentPost(Acc As mDB.Account, Parent As mDB.Message_Post, t As WebApi.Facebook.Comment) As mDB.Message_Post

                'aggiorna messaggio
                Dim Mess = db.TAB.Message_Post.BY.Message_Post.Post_Code(t.id).ToObj

                If Mess Is Nothing Then
                    Mess = New mDB.Message_Post

                    '-------------------------------------------------------------
                    'crea l'account
                    Dim AccCode = t.from.id '  t.user.id_str
                    If AccCode <> "" Then

                        Dim MessAcc = Acc.AddAccountLink(mDB._Account_Link.Type.FOLLOWER, AccCode, IIf(t.from.category = "", AccType.FACEBOOK_USER, AccType.FACEBOOK_PAGE))

                        Mess.Account_Id = MessAcc.Account_Link_Id ' MessAcc.Id
                    Else

                        Mess.Account_Id = 0

                    End If

                    db.InsertOnSubmit(Mess)

                    Mess.Post_Code = t.id
                    Mess.To_Account_Id = Parent.Account_Id

                    If t.message <> "" Then
                        Mess.Post_Text = MyApp.ToUTF8DB(t.message) ' Encoding.Default.GetString(Encoding.Convert(Encoding.UTF8, Encoding.Default, Encoding.UTF8.GetBytes(t.text)))
                    End If

                    Mess.Pubb_Date = t.created_time
                    Mess.Hash_Id = Mess.Post_Text.GetHashCode
                    Mess.Reply_To_Post_Code = Parent.Post_Code
                    Mess.Parent_Post_Update = 1

                    db.SubmitChanges()

                    Return Mess

                Else

                    Return Nothing

                End If

            End Function

            'Public Function UpdateMessagePost(Acc As mDB.Account, t As WebApi.Facebook.Post) As mDB.Message_Post

            '    'aggiorna messaggio
            '    Dim Mess = db.TAB.Message_Post.BY.Message_Post.Post_Code(t.id).ToObj

            '    If Mess Is Nothing Then
            '        Mess = New mDB.Message_Post

            '        '-------------------------------------------------------------
            '        'crea l'account
            '        Dim AccCode = t.from.id '  t.user.id_str
            '        If AccCode <> "" Then

            '            Dim MessAcc = Acc.AddAccountLink(mDB.Account_Link.Type.FOLLOWER, AccCode, IIf(t.from.category = "", NetworkType.FACEBOOK, NetworkType.FACEBOOK_PAGE))
            '            Mess.Account_Id = MessAcc.Account_Link_Id

            '        Else

            '            Mess.Account_Id = 0

            '        End If

            '        db.InsertOnSubmit(Mess)

            '    End If

            '    If Mess.Account_Id <> Acc.Id Or t.comments IsNot Nothing Then

            '        Mess.Post_Code = t.id
            '        If Mess.Account_Id <> Acc.Id Then
            '            Mess.To_Account_Id = Acc.Id
            '            ' aggiungi ai followers
            '        Else
            '            Mess.To_Account_Id = 0
            '        End If

            '        Mess.Post_Text = MyApp.ToUTF8DB(t.message) & " (" & MyApp.ToUTF8DB(t.story) & ")" & " [" & t.type.ToUpper & "]" ' Encoding.Default.GetString(Encoding.Convert(Encoding.UTF8, Encoding.Default, Encoding.UTF8.GetBytes(t.text)))

            '        Mess.Pubb_Date = t.created_time
            '        Mess.Hash_Id = Mess.Post_Text.GetHashCode

            '        db.SubmitChanges()

            '        If t.comments IsNot Nothing Then

            '            Dim add As Boolean = False

            '            For Each comm In t.comments.data
            '                Dim m = Me.UpdateCommentPost(Acc, Mess, comm)
            '                If m IsNot Nothing Then
            '                    add = True
            '                End If
            '            Next

            '            If Not add Then
            '                db.DeleteOnSubmit(Mess)
            '                db.SubmitChanges()

            '            End If

            '        End If

            '    Else

            '        db.ResetChanges()

            '    End If


            '    Return Mess

            'End Function


#End Region

#Region "QUERY"

            Public Sub DownloadQueryPosts(q As mDB.Query, Mode As mDB.Query.UpdateModeType)
                Const NumPostFindEnd = 50
                Const NumPostToDownload = 2000

                Dim tc = New WebApi.Facebook.FacebookClient(Me.oauth2)

                Dim EndDownload = False
                Dim ContinuePrevDownload = False
                Dim Since = ""
                Dim Until = ""
                Dim ResultType = ""

                Dim PostCount = 0

                ' imposto i codici da cui partire
                Dim Codes = q.Post_Last_Code.ToString.Split(",")

                If Codes.Length > 1 Then
                    ContinuePrevDownload = True
                    Since = Codes(0)
                    Until = Codes(1)
                Else
                    Since = q.GetLastPostDateUniversalTimeStamp   ' Me.GetLastQueyPostCod(q)
                End If

                'imposto la query
                Dim query As String = q.Query
                Dim geocode As String = ""
                Dim Lang As String = ""

                If q.Place_Id > 0 Then
                    Dim place = db.TAB.Place.GetByPK(q.Place_Id)
                    geocode = SF("{0},{1},{2}", DBase.Conv.DoubleToDB(place.Lat), DBase.Conv.DoubleToDB(place.Lon), "15mi")
                End If
                If q.Lang_Code <> "" Then
                    Lang = q.Lang_Code
                End If

                If Mode = mDB.Query.UpdateModeType.REALTIME Then
                    ResultType = "recent"
                End If

                Do Until EndDownload

                    'Dim tweets = tc.GetSearch(query, Since_id, Max_id, ResultType, geocode, Lang)
                    Dim tweets = tc.GetSearchPost(query, Since, Until)

                    For Each t In tweets.data

                        Me.UpdateQueryPost(q, t)
                        PostCount += 1

                    Next

                    MyApp.WriteProcLog(SF("(tab)(tab)(tab)update query: {0} - '{1}'", PostCount, q.Query), Task.TaskType.UPDATE_QUERY)

                    If tweets.data.Count > 0 Then
                        'Dim par = HttpUtility.ParseQueryString(tweets.paging.next)
                        'Max_id = par("until")
                        Until = Utils.Conv.ToTimeStamp(tweets.data.Last.created_time.ToUniversalTime)
                    End If

                    q.Post_Last_Code = SF("{0},{1}", Since, Until)
                    db.SubmitChanges()


                    If tweets.data.Count < NumPostFindEnd Or PostCount > NumPostToDownload Then
                        EndDownload = True
                    End If

                    If EndDownload And ContinuePrevDownload Then
                        ContinuePrevDownload = False
                        EndDownload = False
                        PostCount = 0
                        Since = q.GetLastPostDateUniversalTimeStamp
                        Until = ""
                    End If


                Loop

                If EndDownload Then
                    q.Post_Download_Count = PostCount
                    q.Post_Last_Code = ""
                    db.SubmitChanges()
                End If

            End Sub

            Public Function UpdateQueryPost(query As mDB.Query, t As WebApi.Facebook.Post) As mDB._Query_Post

                'aggiorna post
                'Dim Post = db.TAB.Query_Post.BY.Query_Post.Query_Id(query.Id, t.id).ToObj
                Dim Post = query._Tab_Query_Post.BY._Query_Post._Post_Code(t.id).ToObj
                'Dim Post = Acc._Tab_Account_Post.BY._Account_Post._Post_Code(t.id).ToObj

                If Post Is Nothing Then
                    Post = New mDB._Query_Post
                    db.InsertOnSubmit(Post)
                End If

                Post.Query_Id = query.Id
                Post.Post_Code = t.id
                If t.message <> "" Then
                    Post.Post_Text = MyApp.ToUTF8DB(t.message) 'Encoding.Default.GetString(Encoding.Convert(Encoding.UTF8, Encoding.Default, Encoding.UTF8.GetBytes(t.text)))
                End If
                Post.Pubb_Date = t.created_time


                'Post.Share_Count = t.retweet_count

                'If t.user IsNot Nothing Then
                '    Post.Account_Code = t.user.id_str
                '    Post.Account_Username = t.user.screen_name
                '    Post.Account_Follower_Count = t.user.followers_count
                'End If

                'If t.entities IsNot Nothing Then
                '    If t.entities.media IsNot Nothing Then
                '        Post.Image_Url = t.entities.media(0).media_url
                '        'Post.Image_Code = t.entities.media(0).id_str
                '        'Post.Image_Source_Code = t.entities.media(0).source_status_id_str
                '    End If
                'End If

                db.SubmitChanges()

                Return Post

            End Function

#End Region


        End Class
    End Namespace
End Namespace
